/******************************************************************************
 This is a derivative work of the data structure presented in:
 
 http://www.cmcrossroads.com/bradapp/ftp/src/libs/C++/AvlTrees.html

 whose author is Brad Appleton (http://www.bradapp.net/). 
 
 See License.txt for license information about the use of the data
 structure.

 Please, note the links above were valid when this comment was written and 
 may not be valid at the time you read it.
 ******************************************************************************/

#ifndef TST_AVL_PAIR_H
#define TST_AVL_PAIR_H

#include <boost/shared_ptr.hpp>
#include <boost/type_traits.hpp>

namespace cnome { namespace tst_avl {
template <typename T1, typename T2>
struct pair_tst_avl {
    typedef boost::shared_ptr<T1> firstPtrT;
    typedef boost::shared_ptr<T2> secondPtrT;

    firstPtrT  pfirst;
    secondPtrT psecond;
    const T1&  first;
    T2&        second;

    pair_tst_avl(): pfirst(firstPtrT(new T1())), first(*pfirst), psecond (secondPtrT(new T2())), second(*psecond) {}
    pair_tst_avl(const T1& f, const T2& s): pfirst(firstPtrT(new T1(f))), first(*pfirst), psecond(secondPtrT(new T2(s))), second(*psecond) {}
    pair_tst_avl(const T1& f, const T2& s, bool): pfirst(), first(const_cast<T1&>(f)), psecond(), second(const_cast<T2&>(s)) {}
    
    template<typename Other1, typename Other2>
    pair_tst_avl(const pair_tst_avl<Other1, Other2>& right)
    : pfirst(firstPtrT(new T1(right.first))), first(*pfirst), 
      psecond(secondPtrT(new T2(right.second))), second(*psecond) {}  // construct from compatible pair

    ~pair_tst_avl() {}
};

template <class T1, class T2>
pair_tst_avl<
    typename boost::call_traits<T1>::value_type, 
    typename boost::call_traits<T2>::value_type> 
  make_pair_tst_avl(const T1& t1, const T2& t2) {
    return pair_tst_avl<
        typename boost::call_traits<T1>::value_type, 
        typename boost::call_traits<T2>::value_type>(t1, t2);
}

template <class T1, class T2>
pair_tst_avl<
    typename boost::call_traits<T1>::value_type, 
    typename boost::call_traits<T2>::value_type> *
  make_pair_tst_avl_ptr(const T1& t1, const T2& t2) {
    return new pair_tst_avl<
        typename boost::call_traits<T1>::value_type, 
        typename boost::call_traits<T2>::value_type>(t1, const_cast<T2&>(t2));
}

template <class T1, class T2>
pair_tst_avl<
    typename boost::call_traits<T1>::value_type, 
    typename boost::call_traits<T2>::value_type> *
  make_pair_tst_avl_ptr(const T1& t1, const T2& t2, bool) {
    return new pair_tst_avl<
        typename boost::call_traits<T1>::value_type, 
        typename boost::call_traits<T2>::value_type>(t1, const_cast<T2&>(t2), true);
}
}}  // cnome::tst_avl

#endif // TST_AVL_PAIR_H
